<?php

if (!defined('BASEPATH'))
    exit('No direct script access allowed');

class MY_Model extends CI_Model {

    protected $tableName = "";
    protected $primKey = "";
    protected $foreignRel = Array();
    protected $delAttribute = NULL; // default : delete column
    protected $orders = Array();
    public static $dbase = Array();

    protected final function curUserId() {
        // update & check user data
        $this->load->library('session');
        $useremail = $this->session->userdata('useremail');
        $userpwd = $this->session->userdata('userpwd');
        $uid = -1;
        if (!$useremail) {
            //..
        } else {
            if (!$userpwd) {
                //..
            } else {
                // check db
                $this->load->model('User_model');
                $userBasic = $this->User_model->fetchLogin($useremail, $userpwd);
                if ($userBasic != NULL) {
                    $uid = $userBasic->id;
                }
            }
        }
        return $uid;
    }

    public final function setOrders($orders = Array()) {
        $this->orders = $orders;
    }

    public function __construct($tableName = "", $primKey = "id", $foreignRel = Array(), $useDB = "homepage") {
        parent::__construct();
        if (!array_key_exists($useDB, MY_Model::$dbase)) {
            MY_Model::$dbase[$useDB] = $this->load->database($useDB, TRUE);
        }
        $this->db = MY_Model::$dbase[$useDB];
        $this->tableName = $tableName;
        $this->primKey = $primKey;
        $this->foreignRel = $foreignRel;
        foreach ($this->foreignRel as $model) {
            $this->load->model($model);
        }
    }

    public function findById($id, $fetchForeign = false, $depth = 1) {
        $where = Array($this->primKey => $id);
        $result = $this->read($where, $fetchForeign, $depth);
        $resObj = NULL;
        if (count($result) > 0) {
            $resObj = $result[0];
        }
        return $resObj;
    }

    public function findAll($where = Array(), $fetchForeign = false, $depth = 1, $page = -1, $limit = 10) {
        $result = $this->read($where, $fetchForeign, $depth, $page, $limit);
        $resArr = Array();
        if (count($result) > 0) {
            $resArr = $result;
        }
        return $resArr;
    }

    public function updateById($id, $data = Array()) {
        return $this->update(Array($this->primKey => $id), $data);
    }

    public function deleteById($id) {
        if ($this->delAttribute == NULL) {
            return $this->delete(Array($this->primKey => $id));
        } else {
            return $this->update(Array($this->primKey => $id), Array($this->delAttribute => true));
        }
    }

    public function deleteAll($where = Array()) {
        if ($this->delAttribute == NULL) {
            return $this->delete($where);
        } else {
            return $this->update($where, Array($this->delAttribute => true));
        }
    }

    public function updateWhere($where = Array(), $data = Array()) {
        return $this->update($where, $data);
    }

    // -----

    protected function create($data = Array()) {
        $this->db->insert($this->tableName, $data);
        return $this->db->insert_id();
    }

    protected function read($where = Array(), $fetchForeign = false, $depth = 1, $page = -1, $limit = 10) {
        $query = NULL;
        if ($this->delAttribute != NULL) {
            if (is_array($where)) {
                $where = array_merge($where, Array($this->delAttribute => false));
            }
        }
        if (count($this->orders) > 0) {
            foreach ($this->orders as $order) {
                $this->db->order_by($order["by"], $order["opt"]);
            }
        }
        if ($page >= 0) {
            $this->db->limit($limit, ($page * $limit));
        }
        if (is_string($where)) {
            $this->db->where($where);
            $query = $this->db->get($this->tableName);
        } else {
            $query = $this->db->get_where($this->tableName, $where);
        }
        $this->setOrders(); // re-set orders
        $results = $query->result();
        if ($fetchForeign) {
            if ($depth > 0) {
                foreach ($results as $result) {
                    foreach (array_keys(get_object_vars($result)) as $attr) {
                        if (array_key_exists($attr, $this->foreignRel)) {
                            $fetch = "\$objAttr = \$this->" . $this->foreignRel[$attr] . "->findById(\$result->\$attr, true, " . ($depth - 1) . "); \$result->$attr = \$objAttr;";
                            eval($fetch);
                        }
                    }
                }
            }
        }
        return $results;
    }

    protected function update($where = Array(), $data = Array()) {
        return $this->db->update($this->tableName, $data, $where);
    }

    protected function delete($where = Array()) {
        return $this->db->delete($this->tableName, $where);
    }

}
